import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import requests
import json
import os
from threading import Thread
import time

class MediaDownloaderApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Cannice HTTP媒体文件下载器V0.1")
        self.root.geometry("800x600")
        self.root.resizable(True, True)

        # 设置服务器地址和端口
        self.server_ip = tk.StringVar(value="192.168.43.1")  # 默认IP
        self.server_port = tk.StringVar(value="8080")  # 默认端口
        self.download_dir = tk.StringVar(value=os.path.expanduser("~/Downloads"))
        self.files = []
        self.is_loading = False

        # 创建UI
        self.create_widgets()

    def create_widgets(self):
        # 服务器设置区域
        settings_frame = ttk.LabelFrame(self.root, text="服务器设置")
        settings_frame.pack(fill="x", padx=10, pady=5)

        ttk.Label(settings_frame, text="服务器IP:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
        ttk.Entry(settings_frame, textvariable=self.server_ip, width=15).grid(row=0, column=1, padx=5, pady=5)

        ttk.Label(settings_frame, text="端口:").grid(row=0, column=2, padx=5, pady=5, sticky="w")
        ttk.Entry(settings_frame, textvariable=self.server_port, width=8).grid(row=0, column=3, padx=5, pady=5)

        ttk.Button(settings_frame, text="获取文件列表", command=self.get_file_list).grid(row=0, column=4, padx=10, pady=5)

        # 下载目录设置
        ttk.Label(settings_frame, text="下载目录:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
        ttk.Entry(settings_frame, textvariable=self.download_dir, width=30).grid(row=1, column=1, columnspan=3, padx=5, pady=5, sticky="ew")
        ttk.Button(settings_frame, text="浏览", command=self.browse_download_dir).grid(row=1, column=4, padx=10, pady=5)

        # 文件列表区域
        files_frame = ttk.LabelFrame(self.root, text="文件列表")
        files_frame.pack(fill="both", expand=True, padx=10, pady=5)

        # 创建Treeview组件
        columns = ("name", "size", "date")
        self.file_tree = ttk.Treeview(files_frame, columns=columns, show="headings")

        # 设置列标题和宽度
        self.file_tree.heading("name", text="文件名")
        self.file_tree.column("name", width=300)

        self.file_tree.heading("size", text="大小")
        self.file_tree.column("size", width=100, anchor=tk.E)

        self.file_tree.heading("date", text="修改日期")
        self.file_tree.column("date", width=200)

        # 滚动条
        scrollbar = ttk.Scrollbar(files_frame, orient="vertical", command=self.file_tree.yview)
        self.file_tree.configure(yscroll=scrollbar.set)
        scrollbar.pack(side="right", fill="y")
        self.file_tree.pack(fill="both", expand=True)

        # 绑定双击事件
        self.file_tree.bind("<Double-1>", self.on_file_double_click)

        # 下载按钮
        self.download_button = ttk.Button(self.root, text="下载选中文件", command=self.download_selected_file)
        self.download_button.pack(pady=5)

        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side="bottom", fill="x")

    def browse_download_dir(self):
        directory = filedialog.askdirectory()
        if directory:
            self.download_dir.set(directory)

    def get_file_list(self):
        if self.is_loading:
            return

        self.is_loading = True
        self.status_var.set("正在获取文件列表...")

        # 清空现有列表
        for item in self.file_tree.get_children():
            self.file_tree.delete(item)
        self.files = []

        # 在新线程中执行网络请求
        Thread(target=self._fetch_file_list).start()

    def _fetch_file_list(self):
        try:
            server_url = f"http://{self.server_ip.get()}:{self.server_port.get()}/media-list"
            response = requests.get(server_url, timeout=10)
            response.raise_for_status()

            # 解析JSON响应
            response_data = json.loads(response.text)
            self.files = response_data.get("contents", [])

            # 更新UI
            self.root.after(0, self._update_file_list_ui)
            self.root.after(0, lambda: self.status_var.set(f"找到 {len(self.files)} 个文件"))

        except Exception as e:
            self.root.after(0, lambda: messagebox.showerror("错误", f"获取文件列表失败: {str(e)}"))
            self.root.after(0, lambda: self.status_var.set("获取文件列表失败"))
        finally:
            self.is_loading = False

    def _update_file_list_ui(self):
        for file in self.files:
            # 提取文件信息
            if isinstance(file, dict):
                name = file.get("name", "未知文件名")
                size = file.get("file_size", "未知大小")
                date = file.get("time", "未知日期")
            else:
                # 如果file不是字典，假设它是文件名
                name = str(file)
                size = "未知大小"
                date = "未知日期"

            # 添加到Treeview
            self.file_tree.insert("", "end", values=(name, size, date))

    def on_file_double_click(self, event):
        self.download_selected_file()

    def download_selected_file(self):
        selected_items = self.file_tree.selection()
        if not selected_items:
            messagebox.showinfo("提示", "请先选择要下载的文件")
            return

        # 获取选中的文件名
        item = selected_items[0]
        file_name = self.file_tree.item(item, "values")[0]

        self.download_file(file_name)

    def download_file(self, file_name):
        if not os.path.exists(self.download_dir.get()):
            try:
                os.makedirs(self.download_dir.get())
            except Exception as e:
                messagebox.showerror("错误", f"创建下载目录失败: {str(e)}")
                return

        # 显示下载进度对话框
        self.progress_window = tk.Toplevel(self.root)
        self.progress_window.title(f"下载 {file_name}")
        self.progress_window.geometry("400x100")
        self.progress_window.resizable(False, False)
        self.progress_window.transient(self.root)
        self.progress_window.grab_set()

        ttk.Label(self.progress_window, text=f"正在下载: {file_name}").pack(padx=10, pady=5)

        self.progress_var = tk.DoubleVar()
        progress_bar = ttk.Progressbar(self.progress_window, variable=self.progress_var, length=380)
        progress_bar.pack(padx=10, pady=5)

        self.progress_percent = tk.StringVar(value="0%")
        ttk.Label(self.progress_window, textvariable=self.progress_percent).pack(pady=5)

        # 在新线程中执行下载
        Thread(target=self._download_file_thread, args=(file_name,)).start()

    def _download_file_thread(self, file_name):
        try:
            server_url = f"http://{self.server_ip.get()}:{self.server_port.get()}/media/{file_name}"
            save_path = os.path.join(self.download_dir.get(), file_name)

            # 发送GET请求下载文件
            with requests.get(server_url, stream=True, timeout=30) as response:
                response.raise_for_status()

                # 获取文件总大小
                total_size = int(response.headers.get("content-length", 0))
                downloaded_size = 0

                # 写入文件
                with open(save_path, "wb") as f:
                    for chunk in response.iter_content(chunk_size=8192):
                        if chunk:
                            f.write(chunk)
                            downloaded_size += len(chunk)

                            # 更新进度
                            if total_size > 0:
                                progress = (downloaded_size / total_size) * 100
                                self.root.after(0, lambda p=progress: self.progress_var.set(p))
                                self.root.after(0, lambda p=progress: self.progress_percent.set(f"{p:.1f}%"))

            # 下载完成
            self.root.after(0, self.progress_window.destroy)
            self.root.after(0, lambda: messagebox.showinfo("成功", f"文件已下载到: {save_path}"))
            self.root.after(0, lambda: self.status_var.set(f"已下载: {file_name}"))

        except Exception as e:
            self.root.after(0, self.progress_window.destroy)
            self.root.after(0, lambda: messagebox.showerror("错误", f"下载失败: {str(e)}"))
            self.root.after(0, lambda: self.status_var.set("下载失败"))

if __name__ == "__main__":
    root = tk.Tk()
    app = MediaDownloaderApp(root)
    root.mainloop()